; ==============================================================================
; Apple II [$D0 ROM] (341-0016) - Programmer's Aid #1 [1978]
; ------------------------------------------------------------------------------
; Part 2 [$D400~$D4D4]: Apple II BASIC Renumber / Append Subroutines
; Version Two by Steve Wozniak [WOZ], 1978-04-12;
; Copyright (c) 1978 by Apple Computer Inc. All Rights Reserved
; ------------------------------------------------------------------------------
; Instructions are in the Programmer's Aid #1 Installation and Operating Manual
; ==============================================================================
; Analyzed (via McFadden's SourceGen) by James Davis [Last Updated: 2020-07-10]
; ==============================================================================
;
; ****************************************
; * *
; * RENUMBER *
; * >CLR *
; * >START= *
; * >STEP= *
; * >CALL -10531 *
; * =($D6DD) *
; * *
; * OPTIONAL *
; * >FROM= *
; * >TO= *
; * >CALL -10521 *
; * =($D6E7) *
; * *
; * USE RENX ENTRY *
; * FOR RENUMBER ALL *
; * *
; ****************************************
;
; These Entry Points (in box above), -10531 = $D6DD & -10521 = $D6E7, are
; located elsewhere, in another section of binary code. I'll need to get
; "A Round Tuit" (at a later date), if you want to see it (done/analyzed).
; Done, See: Apple II Programmers Aid 1.2.5.$D692~$D716 - Entry Points.
;
; ==============================================================================
; Renumber/Append 6502 Equates:
; ==============================================================================
;
R0L EQU $00 {addr/1} ;Sweet 16 Accumulator Register #0, Low
R0H EQU $01 {addr/1} ;Sweet 16 Accumulator Register #0, High
R11L EQU $16 {addr/1} ;Sweet 16 Register #11, Low
R11H EQU $17 {addr/1} ;Sweet 16 Register #11, High
MEMFUL EQU $E36B ;BASIC Memory Full Error
PRDEC EQU $E51B ;BASIC Print Decimal Number
RNGERR EQU $EE68 ;BASIC Range Error
LOAD EQU $F0DF ;BASIC Load from Tape Subroutine
SW16 EQU $F689 ;Sweet 16 Interpreter (Op-Codes follow it)
CROUT EQU $FD8E ;Print Carriage Return
COUT EQU $FDED ;Print A-Reg to Output Device
ORG $D400
;
; ==============================================================================
; *** SourceGen needs a way to interpret Sweet 16 Operations like the following:
; [See: "SWEET16: The 6502 Dream Machine"; BYTE Magazine, Nov 1977, Pgs 150~159]
; [And: "Apple II Reference Manual (Red Book)"; §C6 Sweet 16 Listing, Pgs 96~99]
; ==============================================================================
;
;
; ==============================================================================
; Renumber/Append 6502 Equates:
; ==============================================================================
; A2 Locations used here (within SW16 Code Blocks, but not listed/decoded above)
; ------------------------------------------------------------------------------
; HIMEM EQU $4C {addr/2} ;BASIC HIMEM Pointer, Low/High
; PPL EQU $CA {addr/2} ;BASIC Program Pointer, Low/High
; PVL EQU $CC {addr/2} ;BASIC Variable Pointer, Low/High
; ==============================================================================
;
;
; ==============================================================================
; General Sweet 16 Equates: Zero-Page Registers used for SW16 Interpreter Op's
; ==============================================================================
; R0 EQU $00 {addr/2} ;Sweet 16 Accumulator Register #0
; R0L EQU $00 {addr/1} ;Sweet 16 Accumulator Register #0, Low
; R0H EQU $01 {addr/1} ;Sweet 16 Accumulator Register #0, High
; ------------------------------------------------------------------------------
; R1 EQU $02 {addr/2} ;Sweet 16 Register #1
; R1L EQU $02 {addr/1} ;Sweet 16 Register #1, Low
; R1H EQU $03 {addr/1} ;Sweet 16 Register #1, High
; ------------------------------------------------------------------------------
; R2 EQU $04 {addr/2} ;Sweet 16 Register #2
; R2L EQU $04 {addr/1} ;Sweet 16 Register #2, Low
; R2H EQU $05 {addr/1} ;Sweet 16 Register #2, High
; ------------------------------------------------------------------------------
; R3 EQU $06 {addr/2} ;Sweet 16 Register #3
; R3L EQU $06 {addr/1} ;Sweet 16 Register #3, Low
; R3H EQU $07 {addr/1} ;Sweet 16 Register #3, High
; ------------------------------------------------------------------------------
; R4 EQU $08 {addr/2} ;Sweet 16 Register #4
; R4L EQU $08 {addr/1} ;Sweet 16 Register #4, Low
; R4H EQU $09 {addr/1} ;Sweet 16 Register #4, High
; ------------------------------------------------------------------------------
; R5 EQU $0A {addr/2} ;Sweet 16 Register #5
; R5L EQU $0A {addr/1} ;Sweet 16 Register #5, Low
; R5H EQU $0B {addr/1} ;Sweet 16 Register #5, High
; ------------------------------------------------------------------------------
; R6 EQU $0C {addr/2} ;Sweet 16 Register #6
; R6L EQU $0C {addr/1} ;Sweet 16 Register #6, Low
; R6H EQU $0D {addr/1} ;Sweet 16 Register #6, High
; ------------------------------------------------------------------------------
; R7 EQU $0E {addr/2} ;Sweet 16 Register #7
; R7L EQU $0E {addr/1} ;Sweet 16 Register #7, Low
; R7H EQU $0F {addr/1} ;Sweet 16 Register #7, High
; ------------------------------------------------------------------------------
; R8 EQU $10 {addr/2} ;Sweet 16 Register #8
; R8L EQU $10 {addr/1} ;Sweet 16 Register #8, Low
; R8H EQU $11 {addr/1} ;Sweet 16 Register #8, High
; ------------------------------------------------------------------------------
; R9 EQU $12 {addr/2} ;Sweet 16 Register #9
; R9L EQU $12 {addr/1} ;Sweet 16 Register #9, Low
; R9H EQU $13 {addr/1} ;Sweet 16 Register #9, High
; ------------------------------------------------------------------------------
; R10 EQU $14 {addr/2} ;Sweet 16 Register #10
; R10L EQU $14 {addr/1} ;Sweet 16 Register #10, Low
; R10H EQU $15 {addr/1} ;Sweet 16 Register #10, High
; ------------------------------------------------------------------------------
; R11 EQU $16 {addr/2} ;Sweet 16 Register #11
; R11L EQU $16 {addr/1} ;Sweet 16 Register #11, Low
; R11H EQU $17 {addr/1} ;Sweet 16 Register #11, High
; ------------------------------------------------------------------------------
; R12 EQU $18 {addr/2} ;Sweet 16 Register #12
; R12L EQU $18 {addr/1} ;Sweet 16 Register #12, Low
; R12H EQU $19 {addr/1} ;Sweet 16 Register #12, High
; ------------------------------------------------------------------------------
; R13 EQU $1A {addr/2} ;Sweet 16 Register #13
; R13L EQU $1A {addr/1} ;Sweet 16 Register #13, Low
; R13H EQU $1B {addr/1} ;Sweet 16 Register #13, High
; ------------------------------------------------------------------------------
; R14 EQU $1C {addr/2} ;Sweet 16 Register #14
; R14L EQU $1C {addr/1} ;Sweet 16 Register #14, Low
; R14H EQU $1D {addr/1} ;Sweet 16 Register #14, High
; ------------------------------------------------------------------------------
; R15 EQU $1E {addr/2} ;Sweet 16 Register #15
; R15L EQU $1E {addr/1} ;Sweet 16 Register #15, Low
; R15H EQU $1F {addr/1} ;Sweet 16 Register #15, High
; ==============================================================================
;
;
; ==============================================================================
; Renumber/Append Sweet 16 Equates: SW16 Registers & Locations used here
; ==============================================================================
; ACC EQU $00 {addr/2} ;R0: Sweet 16 Accumulator
; NEWLOW EQU $01 {addr/1} ;R0H: New Initial Line Number (LNO)
; NEWINCR EQU $02 {addr/1} ;R1L: New LNO Increment (INCR) Value
; LNLO EQU $03 {addr/1} ;R1H: Low LNO of RENUM Range
; LNHI EQU $04 {addr/1} ;R2L: High LNO of RENUM Range
; TBLSTRT EQU $05 {addr/1} ;R2H: LNO Table Start
; TBLINDX1 EQU $06 {addr/1} ;R3L: Pass 1 LNO Table Index
; TBLND EQU $06 {addr/1} ;R3L: Pass 2 LNO Table End
; TBLIM EQU $07 {addr/1} ;R3H: LNO Table Limit
; PRGNDX2 EQU $07 {addr/1} ;R3H: Pass 2 Program Index
; SCR8 EQU $08 {addr/1} ;R4L: Scratch Register
; HMEM EQU $08 {addr/1} ;R4L: HIMEM (End of Program)
; SCR9 EQU $09 {addr/1} ;R4H: Scratch Register
; PRGNDX EQU $09 {addr/1} ;R4H: Pass 1 Program Index
; CHR9 EQU $09 {addr/1} ;R4H: ASCII "0" (Constant Safe)
; PRGNDX1 EQU $0A {addr/1} ;R5L: Pass 1 Program Index 1
; CHRA EQU $0A {addr/1} ;R5L: ASCII "@" (Constant Safe)
; NEWLN EQU $0B {addr/1} ;R5H: Next "New LNO" Assignment
; TBLNDX2 EQU $0B {addr/1} ;R5H: LNO Table Index for Update
; STRCON EQU $0B {addr/1} ;R5H: BASIC String Constant Token
; NEWLN1 EQU $0C {addr/1} ;R6L: Prior "New LNO" Assignment
; MODE EQU $0C {addr/1} ;R6L: LNO Mode Constant
; REM EQU $0C {addr/1} ;R6L: BASIC REM Token
; SCRC EQU $0C {addr/1} ;R6L: Scratch Register for Append
; OLDLN EQU $0D {addr/1} ;R6H: Old LNO for Update
; CPRREG EQU $0D {addr/1} ;R6H: Compare (CPR) Register [Not R13 !!!]
; THEN EQU $0D {addr/1} ;R6H: BASIC THEN Token
; LIST EQU $0D {addr/1} ;R6H: BASIC LIST Token
; DEL EQU $0D {addr/1} ;R6H: BASIC DEL Token
; ==============================================================================
;
;
; ==============================================================================
; Apple II BASIC Renumber Subroutine - Pass 1
; ==============================================================================
;
; ------------------------------------------------------------------------------
; ;Optional Range Entry; Use to Renumber All
D400: 20 89 F6 RENX JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)...
; ------------------------------------------------------------------------------
D403: B0 DFB $B0 ;SUB ACC ;R0:
D404: 33 DFB $33 ;ST LNLO ;Set LNLO=0
D405: 34 DFB $34 ;ST LNHI ;Set LNHI=0
D406: F4 DFB $F4 ;DCR LNHI ;Reduce LNHI (from 0 to -1)
D407: 00 DFB $00 ;RTN ;[Return to 6502 Mode]
; ==============================================================================
; Apple II BASIC Renumber Subroutine
; ==============================================================================
;
; ------------------------------------------------------------------------------
; ;Both BASIC Entry Pt. Calls will Jump Here
D408: 20 89 F6 RENUM JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)...
; ------------------------------------------------------------------------------
D40B: 18 4C 00 HEX 184C00 ;SET HMEM,HIMEM
D40E: 68 DFB $68 ;LDD @HMEM
D40F: 38 DFB $38 ;ST HMEM
D410: 19 CE 00 RNUM3 HEX 19CE00 ;SET SCR9,PVL+2
D413: C9 DFB $C9 ;POPD @SCR9 ;BASIC Var Pnt to ...
D414: 35 DFB $35 ;ST TBLSTRT ;<- TBLSTRT & ...
D415: 36 DFB $36 ;ST TBLNDX1 ;<- TBLNDX1
D416: 21 DFB $21 ;LD NEWLOW ;Copy NEWLOW (Intl) to ...
D417: 3B DFB $3B ;ST NEWLN ;<- NEWLN & ...
D418: 3C DFB $3C ;ST NEWLN1 ;<- NEWLN1
D419: C9 DFB $C9 ;POPD @SCR9 ;BASIC Program Pntr to ...
D41A: 37 DFB $37 ;ST TBLIM ;<- TBLIM & ...
D41B: 39 DFB $39 ;ST PRGNDX ;<- PRGNDX
D41C: 29 PASS1 DFB $29 ;LD PRGNDX
D41D: D8 DFB $D8 ;CPR HMEM ;If PRGNDX >= HMEM, ...
D41E: 03 46 DDB $0346 ;BC PASS2 ;Then Done with Pass 1
D420: 3A DFB $3A ;ST PRGNDX1
D421: 26 DFB $26 ;LD TBLNDX1
D422: E0 DFB $E0 ;INR ACC ;If < 2 Bytes avail in ...
D423: D7 DFB $D7 ;CPR TBLIM ;LNO Table, then Return ...
D424: 03 38 DDB $0338 ;BC MERR ;with "MEM FULL" Message
D426: 4A DFB $4A ;LD @PRGNDX1
D427: A9 DFB $A9 ;ADD PRGNDX ;Add Length to Prog Index
D428: 39 DFB $39 ;ST PRGNDX
D429: 6A DFB $6A ;LDD @PRGNDX1 ;Line Number
D42A: D3 DFB $D3 ;CPR LNLO ;If < LNLO, Goto P1C
D42B: 02 2A DDB $022A ;BNC P1B
D42D: D4 DFB $D4 ;CPR LNHI ;If > LNHI, Goto P1C
D42E: 02 02 DDB $0202 ;BNC P1A
D430: 07 30 DDB $0730 ;BNZ P1C
D432: 76 P1A DFB $76 ;STD @TBLNDX1 ;Add to LNO Table
D433: 00 DFB $00 ;RTN ;[Return to 6502 Mode]
; ----------------------------------- ;Print 'Old Line #' "->" 'New Line #'
; ; [SW16: (R0,R11)] in Decimal:
;
; ------------------------ ;**** 6502 Code Block Start ****
D434: A5 01 LDA R0H ;Get Sweet 16 Register #0, High
D436: A6 00 LDX R0L ;Get Sweet 16 Register #0, Low
D438: 20 1B E5 JSR PRDEC ;Print Decimal Number
D43B: A9 AD LDA #'-' | $80 ;Get a Dash Character
D43D: 20 ED FD JSR COUT ;Print A-Reg to Output Device
D440: A9 BE LDA #'>' | $80 ;Get a Greater Than Sign
D442: 20 ED FD JSR COUT ;Print A-Reg to Output Device
D445: A5 17 LDA R11H ;Get Sweet 16 Register #11, High
D447: A6 16 LDX R11L ;Get Sweet 16 Register #11, Low
D449: 20 1B E5 JSR PRDEC ;Print Decimal Number
D44C: 20 8E FD JSR CROUT ;Print a Carriage Return
; ------------------------ ;**** 6502 Code Block End ****
;
; ------------------------------------------------------------------------------
D44F: 20 8C F6 JSR SW16+3 ;Sweet 16 Interpreter (Op-Codes follow)...
; ------------------------------------------------------------------------------
D452: 2B DFB $2B ;LD NEWLN
D453: 3C DFB $3C ;ST NEWLN1 ;Copy NEWLN to NEWLN1 & ...
D454: A2 DFB $A2 ;ADD NEWINCR ;Increase NEWLN by NEWINCR
D455: 3B DFB $3B ;ST NEWLN
D456: 0D DFB $0D ;HEX 0D ;'NUL' (Will Skip Next Op)
D457: D1 P1B DFB $D1 ;CPR NEWLOW ;If Low LNO < New Low, ...
; ; ; ; ;then "RANGE ERR"
D458: 02 C2 DDB $02C2 ;BNC PASS1 ;Loop if Not
; ----------------------------------- ;------------- ;Else, Print Err Message:
D45A: 00 RERR DFB $00 ;RTN ;[Return to 6502 Mode]
D45B: 4C 68 EE JMP RNGERR ;6502 Code: BASIC Range Error
; ----------------------------------- ;------------- ;Print Err Message:
D45E: 00 MERR DFB $00 ;RTN ;[Return to 6502 Mode]
D45F: 4C 6B E3 JMP MEMFUL ;6502 Code: BASIC Memory Full Error
; ----------------------------------- ;------------- ;[Continue SW16 Process]:
D462: EC P1C DFB $EC ;INR NEWLN1 ;If Hi LNO <= Current NEWLN
D463: DC DFB $DC ;CPR NEWLN1 ;then "RANGE ERR" ...
D464: 02 F4 DDB $02F4 ;BNC RERR ;Go Print Err Message
;
; ==============================================================================
; Apple II BASIC Renumber / Append Subroutine - Pass 2
; ==============================================================================
;
D466: 19 B0 00 PASS2 HEX 19B000 ;CHR9,$00B0 ;SET (Constant)=(ASCII "0")
D469: 1A C0 00 HEX 1AC000 ;CHRA,$00C0 ;SET (Constant)=(ASCII "@")
; ------------------------------------------------------------------------------
; *** NOTE: $C0 is an "@" (AT sign)!--Not an "A" character (as shown in the
; listing in the "Programmer's Aid #1 Installation & Operating Manual")!
; ------------------------------------------------------------------------------
D46C: 27 P2A DFB $27 ;LD PRGNDX2
D46D: D8 DFB $D8 ;CPR HMEM ;If PRGNDX2 = HIMEM, ...
D46E: 03 63 DDB $0363 ;BC DONE ;then Pass 2 is Done
D470: E7 DFB $E7 ;INR PRGNDX2 ;Skip Length Byte
D471: 67 DFB $67 ;LDD @PRGNDX2 ;Line Number
D472: 3D UPDATE DFB $3D ;ST OLDLN ;Save Old LNO
D473: 25 DFB $25 ;LD TBLSTRT
D474: 3B DFB $3B ;ST TBLNDX2 ;Init LNO Table Index
D475: 21 DFB $21 ;LD NEWLOW ;Init NEWLN to NEWLOW
D476: 1C DFB $1C ;HEX 1C ;(Will Skip Next Op)
D477: 2C UD2 DFB $2C ;LD NEWLN1
D478: A2 DFB $A2 ;ADD NEWINCR ;Add INCR to NEWLN1
D479: 3C DFB $3C ;ST NEWLN1
D47A: 2B DFB $2B ;LD TBLNDX2 ;If LNO TBL IDX = TBLND ...
D47B: B6 DFB $B6 ;SUB TBLND ;then Done Scanning LNO TBL
D47C: 03 07 DDB $0307 ;BC UD3
D47E: 6B DFB $6B ;LDD @TBLNDX2 ;Next LNO from Table
D47F: BD DFB $BD ;SUB OLDLN ;Loop to UD2 If Not = OLDLN
D480: 07 F5 DDB $07F5 ;BNZ UD2
D482: C7 DFB $C7 ;POPD @PRGNDX2 ;Replace Old LNO with ...
D483: 2C DFB $2C ;LD NEWLN1 ;Corresponding New Line
D484: 77 DFB $77 ;STD @PRGNDX2
D485: 1B 28 00 UD3 HEX 1B2800 ;SET STRCON,$0028 ;STR CON Token
D488: 1C DFB $1C ;HEX 1C ;(Skips Next Two Ops)
D489: 67 GOTCON DFB $67 ;LDD @PRGNDX2
D48A: FC DFB $FC ;DCR MODE ;If MODE = 0 Update LNO Ref
D48B: 08 E5 DDB $08E5 ;BM1 UPDATE
D48D: 47 ITEM DFB $47 ;LD @PRGNDX2 ;BASIC Token
D48E: D9 DFB $D9 ;CPR CHR9
D48F: 02 09 DDB $0209 ;BNC CHKTOK ;Check Token for Special
D491: DA DFB $DA ;CPR CHRA ;If >= "0" & < "@" ...
D492: 02 F5 DDB $02F5 ;BNC GOTCON ;Skip Const or Update
D494: F7 SPKASC DFB $F7 ;DCR PRGNDX2
D495: 67 DFB $67 ;LDD @PRONDX2 ;Skip all Neg Bytes of ...
D496: 05 FC DDB $05FC ;BM SKPASC ;STR CON, REM or NAME
D498: F7 DFB $F7 ;DCR PRGNDX2
D499: 47 DFB $47 ;LD @PRGNDX2
D49A: DB CHKTOC DFB $DB ;CPR STRCON ;STR CON Token?
D49B: 06 F7 DDB $06F7 ;BZ SKPASC ;Yes, Skip Subseguent Bytes
D49D: 1C 5D 00 HEX 1C5D00 ;SET REM,$005D
D4A0: DC DFB $DC ;CPR REM ;REM Token?
D4A1: 06 F1 DDB $06F1 ;B2 SKPASC ;Yes, Skip Subseguent Line
D4A3: 08 13 DDB $0813 ;BM1 CONTST ;GOSUB, Look for Line #
D4A5: FD DFB $FD ;DCR R13
D4A6: FD DFB $FD ;DCR R13 ;(Token $5F is GOTO)
D4A7: 06 0F DDB $060F ;BZ CONTST
D4A9: 1D 24 00 HEX 1D2400 ;SET THEN,$0024
D4AC: DD DFB $DD ;CPR THEN
D4AD: 06 09 DDB $0609 ;BZ CONTST ;'THEN' LNO, Look for LNO
D4AF: F0 DFB $F0 ;DCR ACC
D4B0: 06 BA DDB $06BA ;BZ P2A ;EOL (Token 01)?
D4B2: 1D 74 00 HEX 1D7400 ;SET LIST,$0074
D4B5: BD DFB $BD ;SUB LIST ;Set Mode if "LIST"|"LIST,"
D4B6: 09 01 DDB $0901 ;BNM1 CONTS2 ;(Tokens $74, $75)
D4B8: B0 CONTST DFB $B0 ;SUB ACC ;Clear Mode for LNO
D4B9: 3C CONTS2 DFB $3C ;ST MODE ;Update Check
D4BA: 01 D1 DDB $01D1 ;BR ITEM
; ==============================================================================
; Apple II BASIC Append Subroutine
; ==============================================================================
;
; ------------------------------------------------------------------------------
; BASIC: 1st LOAD (from Tape) 2nd Integer BASIC Program with high line numbers;
; then CALL -11076 to LOAD & Append 1st Program with low line numbers
; ------------------------------------------------------------------------------
D4BC: 20 89 F6 APPEND JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)...
; ------------------------------------------------------------------------------
D4BF: 1C 4E 00 HEX 1C4E00 ;SET SCRC,HIMEM+2
D4C2: CC DFB $CC ;POPD @SCRC ;Save HIMEM
D4C3: 38 DFB $38 ;ST HMEM
D4C4: 19 CA 00 HEX 19CA00 ;SET SCR9,PPL
D4C7: 69 DFB $69 ;LDD @SCR9
D4C8: 7C DFB $7C ;STD @SCRC ;Set HIMEM to Preserve Prog
D4C9: 00 DFB $00 ;RTN ;[Return to 6502 Mode]
D4CA: 20 DF F0 JSR LOAD ;6502 Code: Load from Tape
;
; ------------------------------------------------------------------------------
; BASIC: CALL -11059 to Recover 2nd Program when Append fails w/ Mem Full Error!
; ------------------------------------------------------------------------------
D4CD: 20 89 F6 RECOVER JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)...
; ------------------------------------------------------------------------------
D4D0: CC DFB $CC ;POPD @SCRC ;Restore HIMEM to Show ...
D4D1: 28 DFB $28 ;LD HMEM ;Both Programs (Old & New)
D4D2: 7C DFB $7C ;STD @SCRC
D4D3: 00 :DONE DFB $00 ;RTN ;[Return to 6502 Mode]
;
D4D4: 60 RTS ;6502 Code: Return to Caller